using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Microblaze.Elf
{
  public class ElfHeader : ElfFormatEntity
  {
    #region Enumerations
    public enum E_Type
    {
      ET_NONE = 0,
      ET_REL  = 1,
      ET_EXEC = 2,
      ET_DYN  = 3,
      ET_MicroblazeComponent = 4,
      ET_LOPROC = 0xff00,
      ET_HIPROC = 0xffff
    }

    public enum E_Version
    {
      EV_NONE = 0,
      EV_CURRENT = 1
    }
    #endregion

    private E_Type e_type;
    private ushort e_machine;
    private E_Version e_version;
    private uint e_entry;
    private uint e_phoff;
    private uint e_shoff;
    private uint e_flags;
    private ushort e_ehsize;
    private ushort e_phentsize;
    private ushort e_phnum;
    private ushort e_shentsize;
    private ushort e_shnum;
    private ushort e_shstrndx;

    #region Properties
    public E_Type E_type
    {
      get { return e_type; }      
    }

    public ushort E_machine
    {
      get { return e_machine; }     
    }

    public E_Version E_version
    {
      get { return e_version; }    
    }

    public uint E_entry
    {
      get { return e_entry; }     
    }

    public ushort E_phnum
    {
      get { return e_phnum; }      
    }

    public ushort E_shnum
    {
      get { return e_shnum; }
    }

    public uint E_shoff
    {
      get { return e_shoff; }
    }

    public uint E_phoff
    {
      get { return e_phoff; }
    }

    public ushort E_shstrndx
    {
      get { return e_shstrndx; }     
    }
    #endregion

    public ElfHeader(ElfFile elfFile)
      : base(elfFile)
    {
    }

    public void Read()
    {
      this.e_type = (E_Type) ReadElf32Half(ElfFile.Reader);

      this.e_machine = ReadElf32Half(ElfFile.Reader);
      this.e_version = (E_Version) ReadElf32Word(ElfFile.Reader);
      this.e_entry = ReadElf32Addr(ElfFile.Reader);
      this.e_phoff = ReadElf32Off(ElfFile.Reader);
      this.e_shoff = ReadElf32Off(ElfFile.Reader);
      this.e_flags = ReadElf32Word(ElfFile.Reader);

      this.e_ehsize = ReadElf32Half(ElfFile.Reader);
      this.e_phentsize = ReadElf32Half(ElfFile.Reader);
      this.e_phnum = ReadElf32Half(ElfFile.Reader);
      this.e_shentsize = ReadElf32Half(ElfFile.Reader);
      this.e_shnum = ReadElf32Half(ElfFile.Reader);
      this.e_shstrndx = ReadElf32Half(ElfFile.Reader);
    }

    public override string ToString()
    {
      StringBuilder str = new StringBuilder();

      str.AppendFormat("e_type      : {0} \n", this.e_type);
      str.AppendFormat("e_machine   : 0x{0:X} \n", this.e_machine);
      str.AppendFormat("e_version   : {0} \n", this.e_version);
      str.AppendFormat("e_entry     : 0x{0:X} \n", this.e_entry);
      str.AppendFormat("e_phoff     : 0x{0:X} \n", this.e_phoff);
      str.AppendFormat("e_shoff     : 0x{0:X} \n", this.e_shoff);
      str.AppendFormat("e_flags     : 0x{0:X} \n", this.e_flags);
      str.AppendFormat("e_ehsize    : 0x{0:X} \n", this.e_ehsize);
      str.AppendFormat("e_phentsize : 0x{0:X} \n", this.e_phentsize);
      str.AppendFormat("e_phnum     : {0} \n", this.e_phnum);
      str.AppendFormat("e_shentsize : 0x{0:X} \n", this.e_shentsize);
      str.AppendFormat("e_shnum     : {0} \n", this.e_shnum);
      str.AppendFormat("e_shstrndx  : 0x{0:X} \n", this.e_shstrndx);

      return str.ToString();
    }

  }
}
